Fragment 基础知识

您所在的位置:网站首页 android fragment和activity的区别 Fragment 基础知识

Fragment 基础知识

2023-07-08 04:56| 来源: 网络整理| 查看: 265

文章目录 前言Fragment 生命周期Fragment生命周期图Fragment与Activity生命周期对比图 Fragment中add、remove、replace区别添加 add替换 replace FragmentTransactiondetach与attach区别detachattach Fragment commit 和 commitAllowingStateLoss 的区别

前言

img

Fragment 生命周期 Fragment生命周期图

img

Fragment与Activity生命周期对比图

img

当一个

fragment

被创建的时候,它会经历以下状态.

onAttach()onCreate()onCreateView()onActivityCreated()

当这个fragment对用户可见的时候,它会经历以下状态。

onStart()onResume() 当这个fragment进入“后台模式”的时候,它会经历以下状态。 onPause()onStop() 当这个fragment被销毁了(或者持有它的activity被销毁了),它会经历以下状态。 onPause()onStop()onDestroyView()onDestroy()onDetach() 在以下的状态中,可以使用Bundle对象保存一个fragment的对象。 onCreate()onCreateView()onActivityCreated() fragment新的状态。 onAttached() —— 当fragment被加入到activity时调用(在这个方法中可以获得所在的activityonCreateView() —— 当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layoutonActivityCreated() —— 当activity的onCreated()方法返回后调用此方法onDestroyView() —— 当fragment中的视图被移除的时候,调用这个方法onDetach() —— 当fragment和activity分离的时候,调用这个方法

一旦activity进入resumed状态(也就是running状态),可以自由地添加和删除fragment了。因此,只有当activity在resumed状态时,fragment的生命周期才能独立的运转,其它时候是依赖于activity的生命周期变化的。

Fragment中onActivityCreated与onViewCreated调用顺序是 onViewCreated要优先于onActivityCreated调用

比如: 直接使用ViewPager实现嵌套的Fragment会让进入Activity中,所有的Fragment都加载完毕,数据都加载好,所有此时可以使用懒加载,切换到哪个Fragment就加载哪个Fragment,这个方式加载不同Fragment不好。最好的是使用一个Fragment,通过replace替换不同Fragment或者通过先将最新的Fragment add,再hide上一个Fragment,最后展示这个Fragment。

Fragment中add、remove、replace区别

首先获取FragmentTransaction对象:FragmentTransaction transaction = getFragmentManager().beginTransaction();

两种方法不同之处:是否要清空容器再添加fragment的区别,用法上add配合hide或是remove使用,replace一般单独出现。

添加 add

一般会配合hide使用:transaction.add(R.id.fragment_container, oneFragment).hide(twoFragment).commit()

第一个参数是容器id, 第二个参数是要添加的fragment,添加不会清空容器中的内容,不停的往里面添加不允许添加同一个fragment实例,这是非常重要的特点。如果一个fragment已经进来的话,再次添加的话会报异常错误的添加进来的fragment都是可见的(visible),后添加的fragment会展示在先添加的fragment上面,在绘制界面的时候会绘制所有可见的view所以大多数add都是和hide或者是remove同时使用的。这样可以节省绘制界面的时间,节省内存消耗,是推荐的用法 替换 replace transaction.replace(R.id.fragment_container, oneFragment).commit() 替换会把容器中的所有内容全都替换掉,有一些app会使用这样的做法,保持只有一个fragment在显示,减少了界面的层级关系。相同之处:每次add和replace都要走一遍fragment 的周期。

处理方式:

首先在add的时候,加上一个tab参数 `transaction.add(R.id.content, ContentFragment,“tag”);然后当ContentFragment引用被回收置空的话,先通过 ContentFragment=FragmentManager.findFragmentByTag("tag"); 找到对应的引用,然后继续上面的hide,show来处理;

在实战中的运用方法:

如果我们使用

replace

来切换页面,那么在每次切换的时候,

Fragment

都会重新实例化,重新加载一边数据,这样非常消耗性能和用户的数据流量。

这是因为replace操作,每次都会把container中的现有的fragment实例清空,然后再把指定的fragment添加进去,就就造成了在切换到以前的fragment时,就会重新实例会fragment。

正确的切换方式是add(),切换时hide(),add()另一个Fragment;再次切换时,只需hide()当前,show()另一个。

使用:

public void addFragment(Fragment from, Fragment to) { if (!to.isAdded()) { // 先判断是否被add过 transaction.hide(from).add(R.id.content_frame, to).commit(); // 隐藏当前的fragment,add下一个到Activity中 } else { transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个 }

复制

FragmentTransaction

FragmentTransaction事务回滚使用方法:

在transaction.commit()之前,使用addToBackStack()将其添加到回退栈中。

transaction.addToBackStack(String tag);

在需要回退时,使用popBackStack()将最上层的操作弹出回退栈。

manager.popBackStack();

这里的popBackStack()是弹出默认的最上层的栈顶内容。

当栈中有多层时,我们可以根据id或TAG标识来指定弹出到的操作所在层。函数如下:

void popBackStack(int id, int flags); void popBackStack(String name, int flags);

复制

其中:

参数int id是当提交变更时transaction.commit()的返回值。

参数string name是transaction.addToBackStack(String tag)中的tag值;

int flags

有两个取值:0或

FragmentManager.POP_BACK_STACK_INCLUSIVE

当取值0时,表示除了参数一指定这一层之上的所有层都退出栈,指定的这一层为栈顶层;当取值POP_BACK_STACK_INCLUSIVE时,表示连着参数一指定的这一层一起退出栈; detach与attach区别 detach

detach():会将view与fragment分离,将此将view从viewtree中删除,而且将fragment从Activity的ADD队列中移除,所以在使用detach()后,使用fragment::isAdded()返回的值是false;但此fragment实例并不会删除,此fragment的状态依然保持着使用,所以在fragmentManager中仍然可以找到,即通过FragmentManager::findViewByTag()仍然是会有值的。

attach

attach():显然这个方法与detach()所做的工作相反,它一方面利用fragment的onCreateView()来重建视图,一方面将此fragment添加到ADD队列中;这里最值得注意的地方在这里:由于是将fragment添加到ADD队列,所以只能添加到列队头部,所以attach()操作的结果是,最新操作的页面始终显示在最前面,由于这里会将fragment添加到Activity的ADD队列中,所以在这里调用fragment::isAdded()将返回True;

系统BUG——add()和replace()不能一起使用

Fragment commit 和 commitAllowingStateLoss 的区别

如果activity的状态被保存了,这里再提交就会检查这个状态,符合条件就抛出一个异常来终止应用进程。也就是说在activity调用了onSaveInstanceState()之后,再commit一个事务就会出现该异常。那如果不想抛出异常,也可以很简单调用commitAllowingStateLoss()方法来略过这个检查就可以了,但是Google说这是危险的,在官方文档上有如下描述:

Like {@link #commit} but allows the commit to be executed after an activity’s state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.

意思是如果activity随后需要从它保存的状态中恢复,这个commit是会丢失的。因此它仅仅适用在ui状态的改变对用户来说是可以接受的。

结论:

在activity的生命周期方法中提交事务要小心,越早越好,比如onCreate。也可以在接收用户的输入时来提交。尽量避免在onActivityResult()方法中提交。避免在异步的回调方法中执行commit。因为他们感知不到当前activity生命周期的状态。使用commitAllowingStateLoss()代替commit()。相比于crash,ui状态的改变对用户来说是可以接受的。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3